package com.qf.myrbac.annotation;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qf.myrbac.sys.entity.SysRoleDept;
import com.qf.myrbac.sys.entity.SysUser;
import com.qf.myrbac.sys.entity.SysUserRole;
import com.qf.myrbac.sys.service.SysDeptService;
import com.qf.myrbac.sys.service.SysRoleDeptService;
import com.qf.myrbac.sys.service.SysUserRoleService;
import com.qf.myrbac.utils.Constants;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@Aspect//代表该类是一个切面
public class DataFilterAspect {
    @Autowired
    SysUserRoleService userRoleService;
    @Autowired
    SysRoleDeptService roleDeptService;
    @Autowired
    SysDeptService deptService;

    //该切点切的是加了@DataFilter注解的方法
    @Pointcut("@annotation(com.qf.myrbac.annotation.DataFilter)")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        DataFilter dataFilter = method.getAnnotation(DataFilter.class);
        String dataField = dataFilter.dataField();
        String deptStr = getDeptStr();
        Object[] args = joinPoint.getArgs();
        Object arg = args[0];
        if (deptStr == null) {
            return;
        }
        if (deptStr.equals("()")) {
            ((Map) arg).put(Constants.DATA_FILETER, "(dept_id in (-1))");
            return;
        }
        String sql = "(" + dataField + " in " + deptStr + ")";
        //通过反射API获取DataFilter注解中配置的数据库部门id对应的字段名称
        if (arg != null && arg instanceof Map) {
            ((Map) arg).put(Constants.DATA_FILETER, sql);
        }
    }

    /**
     * 获取当前登录用户的数据权限字符串
     * 如果是管理员，那么直接获取全部部门信息
     * 如果是非管理员，只获取有权限的部门
     *
     * @return
     */
    private String getDeptStr() {
        //根据当前登录用户查询用户的角色
        Subject subject = SecurityUtils.getSubject();
        SysUser user = (SysUser) subject.getPrincipal();
        if (Constants.SUPER_ADMIN_ID.equals(user.getUserId())) {
            /*List<SysDept> deptList = deptService.list();
            return deptList.stream()
                    .map(dept->dept.getDeptId().toString())
                    .collect(Collectors.joining(",", "(", ")"));*/
            return null;
        }
        QueryWrapper<SysUserRole> userRoleQueryWrapper = new QueryWrapper<>();
        userRoleQueryWrapper.select("role_id");
        userRoleQueryWrapper.eq("user_id", user.getUserId());
        List<Object> roleIdList = userRoleService.listObjs(userRoleQueryWrapper);
        //在查询该角色拥有哪些部门id
        QueryWrapper<SysRoleDept> roleDeptQueryWrapper = new QueryWrapper<>();
        roleDeptQueryWrapper.select("dept_id");
        roleDeptQueryWrapper.in("role_id", roleIdList);
        List<Object> deptIdList = roleDeptService.listObjs(roleDeptQueryWrapper);
        String deptIds = deptIdList.stream()
                .map(Object::toString)
                .collect(Collectors.joining(",", "(", ")"));
        return deptIds;
    }
}
